home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Information
/
CSMP Digest
/
volume 3
/
csmp-digest-v3-064
< prev
next >
Wrap
Text File
|
1995-12-31
|
53KB
|
1,477 lines
Received-Date: Sat, 8 Oct 1994 14:49:48 +0100
From: pottier@clipper.ens.fr (Francois Pottier)
Subject: csmp-digest-v3-064
To: csmp-digest@ens.fr
Date: Sat, 8 Oct 1994 14:49:41 +0100 (MET)
X-Mailer: ELM [version 2.4 PL23]
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
Errors-To: listman@ens.fr
Reply-To: pottier@clipper.ens.fr
X-Sequence: 69
C.S.M.P. Digest Sat, 08 Oct 94 Volume 3 : Issue 64
Today's Topics:
Help!! argc, argv on Macintosh
How to Check if drivers are open
Is it possible to notify another mac?
Memory moving and Inits
Self-disposing notification crashes
[CWWWW] PowerPlant Tour document available
The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
(pottier@clipper.ens.fr).
The digest is a collection of article threads from the internet newsgroup
comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi-
regularly and want an archive of the discussions. If you don't know what a
newsgroup is, you probably don't have access to it. Ask your systems
administrator(s) for details. If you don't have access to news, you may
still be able to post messages to the group by using a mail server like
anon.penet.fi (mail help@anon.penet.fi for more information).
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject. The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
nef.ens.fr). Article threads are not added to the digest until the last
article added to the thread is at least two weeks old (this is to ensure that
the thread is dead before adding it to the digest). Article threads that
consist of only one message are generally not included in the digest.
The digest is officially distributed by two means, by email and ftp.
If you want to receive the digest by mail, send email to listserv@ens.fr
with no subject and one of the following commands as body:
help Sends you a summary of commands
subscribe csmp-digest Your Name Adds you to the mailing list
signoff csmp-digest Removes you from the list
Once you have subscribed, you will automatically receive each new
issue as it is created.
The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest.
Questions related to the ftp site should be directed to
scott.silver@dartmouth.edu. Currently no previous volumes of the CSMP
digest are available there.
Also, the digests are available to WAIS users. To search back issues
with WAIS, use comp.sys.mac.programmer.src. With Mosaic, use
http://www.wais.com/wais-dbs/comp.sys.mac.programmer.html.
-------------------------------------------------------
>From victor chong <victorc@sleepy.cc.utexas.edu>
Subject: Help!! argc, argv on Macintosh
Date: 22 Sep 1994 21:19:15 GMT
Organization: UT Austin
Hi,
I was wondering if someone could enlighten me concerning
the usage of argv and argc when programming on the Macintosh.
I'm using Symantec C++.
Does the Mac allows this kind of communication with the
OS or is there another method.
Any kind of help will be much welcome.
Thank you very much.
victor
victorc@sleepy.cc.utexas.edu
+++++++++++++++++++++++++++
>From Eric.M.Kidd@dartmouth.edu (Eric M. Kidd)
Date: 23 Sep 1994 00:11:36 GMT
Organization: Dartmouth College, Hanover, NH
argc and argv do not work at all on any normal mac setup. Sorry.
The following program fragment gives an idea of how to get the
old-fashioned app params (files to open or print). If you want to do
anything more complicated, you'll need to use Apple Events.
/* openingFiles( )
**
** Determine if we have parameters. The old-style app parameters are
used for
** the sake of SPEED. Apple Events are too slow, and I only have
partial docs.
** Help in acquiring copies of Inside Macintosh always welcome...
*/
Boolean openingFiles( )
{
short message;
short count;
CountAppFiles( &message, &count );
return ( message == 0 && count > 0 );
}
/* openFiles( )
**
** Go through files one by one, processing them along the way.
*/
void openFiles( )
{
FSSpec cur;
AppFile aFile;
short count;
short i;
short mess;
/* I'm not bothering to check for print messages--my app shouldn't get
any */
CountAppFiles( &mess, &count );
for ( i = 1; i <= count; i++ )
{
/* get file and convert from working dir to FSSpec */
GetAppFiles( i, &aFile );
FSMakeFSSpec( aFile.vRefNum, 0, aFile.fName, &cur );
processFile( &cur );
}
}
main( )
{
initMacintosh( );
initApplication( );
if ( openingFiles( ) )
openFiles( );
else
runApplication( );
}
+++++++++++++++++++++++++++
>From ruhl@du.edu (ROBERT A. UHL )
Date: Fri, 23 Sep 1994 15:34:11 GMT
Organization: University of Denver
Does anybody have the format of the Handle returned by
GetAppParms()? I don't have IM and have to figure out what the
functions do from the headers. Any help would be appreciated.
--
- ------------------------------------
| Bob Uhl | Spectre |
| U of D | Baron Robert von Raetzin |
+++++++++++++++++++++++++++
>From Carl R. Osterwald <carl_osterwald@nrel.gov>
Date: Fri, 23 Sep 1994 20:48:32 GMT
Organization: National Renewable Energy Laboratory
In article <35ssck$m3a@geraldo.cc.utexas.edu> victor chong,
victorc@sleepy.cc.utexas.edu writes:
> I was wondering if someone could enlighten me concerning
>the usage of argv and argc when programming on the Macintosh.
>I'm using Symantec C++.
> Does the Mac allows this kind of communication with the
>OS or is there another method.
Just use the Symantec console package. You will need to add one key
element, a ccommand() call, before you access argv/argc. This puts up a
dialog box that allows you to type in the command line parameters.
ccommand() was documented in the Think C 5 manuals, in 6 and 7 it is
online inside the free version of Think Reference (I have not verified
this personally).
For disk I/O be sure to check the c.s.m.p PD programming FAQ compiled by
Jon Watte.
+++++++++++++++++++++++++++
>From rrk@rahul.net (Bob R. Kenyon)
Date: Sat, 24 Sep 1994 05:54:04 GMT
Organization: La Casita de Las Pulgas, San Jose, CA
In article <35ssck$m3a@geraldo.cc.utexas.edu>, victor chong
<victorc@sleepy.cc.utexas.edu> wrote:
> Hi,
> I was wondering if someone could enlighten me concerning
> the usage of argv and argc when programming on the Macintosh.
> I'm using Symantec C++.
> Does the Mac allows this kind of communication with the
> OS or is there another method.
> Any kind of help will be much welcome.
> Thank you very much.
Yeah, if you look in Think Reference, they talk about a function called
ccommand. When your program starts, it throws up a window that allows you
to redirect input and output, and enter command line arguments. It's
pretty funny actually, but not really "Mac" in behavior.
Their code example looks like this:
/* CODE EXAMPLE #1 */
#include <stdio.h>
#include <console.h>
main(int argc, char **argv)
{
int i;
argc = ccommand(&argv); // this is the command that throws up the window
for (i=0; i<argc; i++)
printf ("%s ", argv[i]);
printf ("\n");
}
I use this technique all the time for my programming classes, because they
haven't covered any kind of windowing stuff.
Hope this helps,
Bob
--
Bob Kenyon | "Pilots take no special joy
Beautiful Downtown San Jose, CA | in walking. Pilots like
rrk@rahul.net | flying." -- Neil Armstrong
---------------------------
>From ferrari@netaxs.com (Darrell Turner)
Subject: How to Check if drivers are open
Date: Thu, 22 Sep 1994 13:26:38 -0500
Organization: Haha, None here
I'm trying to figure out how to check if a driver is open by only
specifying the driver name. I want it to work for .IPP .AOut, and others
such as ram serail drivers for Hurdlers, etc.
My problem is that I can't figure out if it's open without first knowing
the driver unit number. I was going to walk the UnitTable checking for the
Driver Name in the DCtlEntry, but I soon discovered that the name is in
there. This is my current code, and it doesn't work, how can I get this
working? (The GetNamedResource returns nil, even on stuff I know is in the
System file like .AOut.
function GetNamedDCtlEntry (driverName: str255): DCtlHandle;
type
Ptr2Word = ^integer;
Ptr2Byte = ^byte;
const
UnitNtryCnt = $1D2; {[GLOBAL VAR] count of entries in unit table
[word]}
RomMapInsert = $B9E;{[GLOBAL VAR] (byte) determines if we should link in
map}
var
rID: integer;
rType: ResType;
hand: handle;
begin
SetResLoad(false);
Ptr2Byte(RomMapInsert)^ := 1;
hand := GetNamedResource('DRVR', driverName);
SetResLoad(true);
GetResInfo(hand, rID, rType, driverName);
if (rID >= 0) and (rID <= Ptr2Word(UnitNtryCnt)^) then
GetNamedDCtlEntry := GetDCtlEntry(rID)
else
GetNamedDCtlEntry := nil;
end;
begin
dctl := GetNamedDCtlEntry('.IPP');
if dCtl = nil then
Quit(noErr);
Init;
repeat
HandleEvents;
until (BitTst(@dctl^^.dCtlFlags, 5) or done);
{...}
end.
+++++++++++++++++++++++++++
>From resnick@uiuc.edu (Pete Resnick)
Date: Fri, 23 Sep 1994 12:36:16 -0500
Organization: University of Illinois at Urbana-Champaign
In article <ferrari-220994132639@slip-55.netaxs.com>, ferrari@netaxs.com (Darrell Turner) wrote:
> I'm trying to figure out how to check if a driver is open by only
> specifying the driver name. I want it to work for .IPP .AOut, and others
> such as ram serail drivers for Hurdlers, etc.
>
> My problem is that I can't figure out if it's open without first knowing
> the driver unit number. I was going to walk the UnitTable checking for the
> Driver Name in the DCtlEntry, but I soon discovered that the name is in
> there.
Yes it is. It's in the driver itself, which is pointed to by the DCtl
entry. Here's some code (in C; the conversion to Pascal is pretty easy):
/* Structure of the driver resource */
typedef struct {
short drvrFlags;
short drvrDelay;
short drvrEMask;
short drvrMenu;
short drvrOpen;
short drvrPrime;
short drvrCtl;
short drvrStatus;
short drvrClose;
unsigned char drvrName[];
unsigned char drvrRoutines[];
} DriverStruct, *DriverPtr, **DriverHandle;
#if define(__SYSEQU__)
#define UTABLEBASE (* (DCtlHandle **)UTableBase)
#define UNITNTRYCNT (* (short *)UnitNtryCnt)
#elif defined(__LOWMEM__)
#define UTABLEBASE (DCtlHandle *)LMGetUTableBase()
#define UNITNTRYCNT LMGetUnitNtryCnt()
#else
#define UTABLEBASE UTableBase
#define UNITNTRYCNT UnitNtryCnt
#endif
#ifndef dOpened
# define dOpened 0x0020
#endif /* dOpened */
#ifndef dRAMBased
# define dRAMBased 0x0040
#endif /* dRAMBased */
short GetDrvrRefNum(StringPtr drvrName)
{
short unitNum;
DCtlPtr curDCtlPtr, *curDCtlHndl, **UTableEntry;
DriverPtr curDrvrPtr;
/* Walk through the Unit Table */
UTableEntry = UTABLEBASE;
for(unitNum = 0; unitNum < UNITNTRYCNT; ++unitNum) {
if((curDCtlHndl = *UTableEntry++) != nil) {
curDCtlPtr = *curDCtlHndl;
/* Get the pointer to the driver */
curDrvrPtr = (DriverPtr)curDCtlPtr->dCtlDriver;
/* If this is a RAM driver, it's a handle. ROM is a pointer */
if((curDCtlPtr->dCtlFlags & dRAMBased) && (curDrvrPtr != nil))
curDrvrPtr = *(DriverPtr *)curDrvrPtr;
/* Does the driver name match? */
if(curDrvrPtr != nil)
if(EqualString(drvrName, curDrvrPtr->drvrName, false, true))
return(~unitNum);
}
}
return(0);
}
Boolean IsDriverOpen(StringPtr drvrName)
{
short unitNum;
DCtlPtr curDCtlPtr, *curDCtlHndl, **UTableEntry;
DriverPtr curDrvrPtr;
/* Walk through the Unit Table */
UTableEntry = UTABLEBASE;
for(unitNum = 0; unitNum < UNITNTRYCNT; ++unitNum) {
if((curDCtlHndl = *UTableEntry++) != nil) {
curDCtlPtr = *curDCtlHndl;
/* Get the pointer to the driver */
curDrvrPtr = (DriverPtr)curDCtlPtr->dCtlDriver;
/* If this is a RAM driver, it's a handle. ROM is a pointer */
if((curDCtlPtr->dCtlFlags & dRAMBased) && (curDrvrPtr != nil))
curDrvrPtr = *(DriverPtr *)curDrvrPtr;
/* Does the driver name match? */
if(curDrvrPtr != nil)
if(EqualString(drvrName, curDrvrPtr->drvrName, false, true))
return((curDCtlPtr->dCtlFlags & dOpened) != 0);
}
}
return(false);
}
Note: There is an omission in the Universal headers LowMem.h because it
does not define LMGetUnitNtryCnt or LMSetUnitNtryCnt. For the 68000
versions, add:
#define LMGetUnitNtryCnt() (* (short *) 0x01D2)
#define LMSetUnitNtryCnt(UnitNtryCntValue) ((* (short *) 0x01D2) = (UnitNtryCntValue))
I don't know what to do about the PowerPC versions.
pr
--
Pete Resnick (...so what is a mojo, and why would one be rising?)
Doctoral Student - Philosophy Department, Gregory Hall, UIUC
System manager - Cognitive Science Group, Beckman Institute, UIUC
Internet: resnick@uiuc.edu
+++++++++++++++++++++++++++
>From csuley@netcom.com (Christopher S. Suley)
Date: Sat, 24 Sep 1994 05:58:12 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
Here's some code I use to find a driver in the unit table.
It's lightly adapted from Pete Resnick's excellent Driver 2.2,
available at sumex and umich and mirrors thereof.
It's in C, but the translation to Pascal should be pretty easy.
typedef struct
{
short drvrFlags;
short drvrDelay;
short drvrEMask;
short drvrMenu;
short drvrOpen;
short drvrPrime;
short drvrCtl;
short drvrStatus;
short drvrClose;
unsigned char drvrName[1]; /* actually variable length p-string */
}
DriverStruct, *DriverPtr;
short
FindDriver( void )
{
Str255 drvrName;
DCtlHandle hCurDCE;
DriverPtr pCurDrvr;
short sDrvrNum;
GetIndString( drvrName, krMiscStrings, ksiDriverNameIndex );
for ( sDrvrNum = LMGetUnitNtryCnt() ; sDrvrNum >= 0 ; --sDrvrNum )
{
hCurDCE = GetDCtlEntry( ~sDrvrNum );
if ( hCurDCE )
{
pCurDrvr = ( DriverPtr ) (**hCurDCE).dCtlDriver;
if ( ((**hCurDCE).dCtlFlags & dRAMBased) && pCurDrvr )
{
pCurDrvr = *( DriverPtr * ) pCurDrvr;
}
if ( pCurDrvr &&
EqualString( drvrName, pCurDrvr->drvrName, false, true ) )
{
return ~sDrvrNum;
}
}
}
return 0;
}
--
Want some? <slap, thud> csuley@netcom.com
Want some? <slap, thud> ChrisSuley@{eworld,aol}.com
---------------------------
>From altitude@umich.edu (Alex Tang)
Subject: Is it possible to notify another mac?
Date: 23 Sep 1994 21:09:51 GMT
Organization: University of Michigan
Hi folks.
I was wondering if it was possible to pull up a dialog box or alert box on
another mac via either AppleTalk or IP.
Me 'n some friends want to write an app that will (in it's most simple
incarnation) open up an alert box on another mac and give them a piece of
information.
In it's most complicated incarnation, we would really like to be able to
have one mac contact the notification manager on another mac, and run a
program on that mac.
This is all presuming we know the AppleTalk node or IP address of the
sending and receiving mac.
Thanx
...alex...
--
Alex Tang | UM-SNRE | UM-ITD/US Consultant II
ALTITUDE@UMICH.EDU | Student | UM-SNRE-NCEET: Systems Admin
PGP via finger. | Systems Admin |http://www.snre.umich.edu/users/altitude
This space for rent|Comp.Consut III| An eye for an eye leaves everyone blind.
+++++++++++++++++++++++++++
>From nick+@pitt.edu ( nick.c )
Date: Fri, 23 Sep 94 20:42:20 GMT
Organization: The Pitt, Chemistry
In Article <35vg70$7v6@lastactionhero.rs.itd.umich.edu>, altitude@umich.edu
(Alex Tang) wrote:
>I was wondering if it was possible to pull up a dialog box or alert box on
>another mac via either AppleTalk or IP.
>
>Me 'n some friends want to write an app that will (in it's most simple
>incarnation) open up an alert box on another mac and give them a piece of
>information.
>
>In it's most complicated incarnation, we would really like to be able to
>have one mac contact the notification manager on another mac, and run a
>program on that mac.
Possible and been done. I remember seeing a notification like
program on Umich... forget the name... "Broadcast"?. Dunno.
Anyway, as I recall you have to have program linking on on the
receiving mac, and have to have loaded an extension on the
receiving mac that takes your message and forwards it to the
local notification manager. You could also create an extension
that sends out apple events, so could launch a local program
when keyed remotely. I'd check out NIM:networking for more
details, luck
-- nick
_/ _/ _/ _/_/_/ _/ _/
Interet: nick@pitt.edu _/_/ _/ _/ _/ _/ _/_/_/
eWorld: nick _/ _/_/ _/ _/ _/ _/
CIS: 71232,766 _/ _/ _/ _/_/_/ _/ _/
+++++++++++++++++++++++++++
>From jonasw@lysator.liu.se (Jonas Wallden)
Date: 24 Sep 1994 21:19:28 GMT
Organization: (none)
altitude@umich.edu (Alex Tang) writes:
>Hi folks.
>
>I was wondering if it was possible to pull up a dialog box or alert box on
>another mac via either AppleTalk or IP.
>
>Me 'n some friends want to write an app that will (in it's most simple
>incarnation) open up an alert box on another mac and give them a piece of
>information.
>
>In it's most complicated incarnation, we would really like to be able to
>have one mac contact the notification manager on another mac, and run a
>program on that mac.
>
>This is all presuming we know the AppleTalk node or IP address of the
>sending and receiving mac.
A nice little hack is 'Radiation + Trigger' which can be used to fake
error messages on anoter Mac's screen. Very useful in lab rooms... :-)
It is an INIT that receives messages through the PPC Toolbox and displays
them as Notification Manager alerts.
BTW, the default message is 'The radiation shield on your Macintosh has
failed. Please step back 5 feet.' which explains its name... Use with
care on newbies!
--
`.`. Jonas Wallden `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.
`.`.`. Internet: jonasw@lysator.liu.se `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.
`.`.`.`. AppleLink: sw1369 `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.
---------------------------
>From jlawrie@malibu.sfu.ca (John William Lawrie)
Subject: Memory moving and Inits
Date: 16 Sep 94 17:13:25 GMT
Organization: Simon Fraser University
Hi. I want to have an extension that performs periodic taks. I have
a skeleton extension that does this already, but the problem is, I
will want to call toolbox routines that will call the memory manager.
Is there a way around this?
John@helix.net
+++++++++++++++++++++++++++
>From onyxtech@aol.com (OnyxTech)
Date: 17 Sep 1994 04:26:02 -0400
Organization: America Online, Inc. (1-800-827-6364)
In article <jlawrie.779735605@sfu.ca>, jlawrie@malibu.sfu.ca (John William
Lawrie) writes:
> Hi. I want to have an extension that performs periodic
> taks. I have a skeleton extension that does this already,
> but the problem is, I will want to call toolbox routines
> that will call the memory manager. Is there a way around
> this?
It's ok to move memory in a trap patch, but It all depends on what you're
using to trigger your extension code? If you're installing a time manager
or VBL routine, forget trying to move memory during that code because they
can/will be executed during interupt time and moving memory then is a
strict no no. If you are triggering your extension code off a trap patch,
them make sure it is a trap patch that can move memory. Then you're ok.
If you are triggering off a trap patch that isn't documented as moving
memory, you'd better change your code because you'll eventually get in
trouble. And since I'm not sure what you're patching, better make sure
that what your trap patch calls does not lead to what you're patching.
Re-entrant city unless you handle it correctly.
dEVoN
+++++++++++++++++++++++++++
>From jcornish@netcom.com (Jud Cornish)
Date: Sun, 18 Sep 1994 08:32:34 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
To perform periodic tasks that may move/purge memory:
A simple solution is to patch a trap (or several) that are known to
move/purge memory and are commonly called. I did some "OS Profiling" of
my own to identify a set of traps that I could patch that would give
frequent time to such a task. The other objective was to get time when
apps, the OS or the Toolbox is in a tight loop such as while tracking a
close box. If you patch any one trap, there will be times when you can go
for quite some time without an opportunity to snag some time. I shouldn't
go into the details, but with some common sense (and a little time with
macsbug) one can pick a pretty good set of traps. All this is only
necessary if you have a really critical time based task. Not critical in
accuracy, but in avoiding long pauses. All this is necessary because of
the way "multi-tasking" is done on the mac. Processes are only granted
time when others share it.
Another option would be to install a driver which requested periodic time.
This is actually harder than just patching _SystemTask, which I believe
would function identically.
Yet another option is to pre-allocate some memory with your INIT, then eat
it up as you need it. In a sense, depending on the complexity of your
memory use, you can just start filling up a simple buffer with data, or
you could make your own sub memory manager!!!
A hybrid solution is to perform periodic tasks via the time manager, with
accuracy and nearly guaranteed time, then when you fill up your buffer (or
get sufficiently close to it), you set a flag which a _SystemTask patch
can use to know when to grow the buffer. You would need to temporarily
suspend your use of the buffer while the patch is growing (and probably
moving) it. This can be done with another flag manipulated just before
and after the SetHandleSize. The periodic task would always make sure this
flag was clear before dereferencing the handle and using the buffer.
I have little idea what your actual needs are but I hope that this
discussion is helpful. Hopefully, a simple patch will suffice. As far as
I have seen (68k sys 7.5), the OS still calls _SystemTask periodically.
If this is indeed the case, it is a good target as other processes will
expect to share time when this happens (usually from a _waitNextEvent
call).
Any comments on my comments would be appreciated.
Erik J. Rogers
+++++++++++++++++++++++++++
>From resnick@uiuc.edu (Pete Resnick)
Date: Sun, 18 Sep 1994 13:00:37 -0500
Organization: University of Illinois at Urbana-Champaign
In article <jlawrie.779735605@sfu.ca>, jlawrie@malibu.sfu.ca (John William
Lawrie) wrote:
> Hi. I want to have an extension that performs periodic taks. I have
> a skeleton extension that does this already, but the problem is, I
> will want to call toolbox routines that will call the memory manager.
> Is there a way around this?
My personal favorite is to use a Time Manager task to do the periodic
part, and have the completion proc for the Time Manager routine post a
Notification Manager request that has all the fields except nmResp
cleared. In the notification response, you can do whatever you want to do
since it is Memory Manager safe.
pr
--
Pete Resnick (...so what is a mojo, and why would one be rising?)
Doctoral Student - Philosophy Department, Gregory Hall, UIUC
System manager - Cognitive Science Group, Beckman Institute, UIUC
Internet: resnick@uiuc.edu
+++++++++++++++++++++++++++
>From Jaeger@fquest.com (Brian Stern)
Date: 19 Sep 1994 05:03:25 GMT
Organization: The University of Texas at Austin, Austin, Texas
In article <jlawrie.779735605@sfu.ca>, jlawrie@malibu.sfu.ca (John William
Lawrie) wrote:
< Hi. I want to have an extension that performs periodic taks. I have
< a skeleton extension that does this already, but the problem is, I
< will want to call toolbox routines that will call the memory manager.
< Is there a way around this?
<
< John@helix.net
A jGNEFilter is a simple way to get periodic time and you can move memory
if you need to. The only problem is that you aren't guaranteed that it
will be called frequently.
--
Brian Stern :-{)}
Jaeger@fquest.com
+++++++++++++++++++++++++++
>From blob@apple.com (Brian Bechtel)
Date: 24 Sep 1994 14:39:56 -0700
Organization: Apple Computer, Inc., Cupertino, California
Jaeger@fquest.com (Brian Stern) writes:
>In article <jlawrie.779735605@sfu.ca>, jlawrie@malibu.sfu.ca (John William
>Lawrie) wrote:
>< Hi. I want to have an extension that performs periodic taks. I have
>< a skeleton extension that does this already, but the problem is, I
>< will want to call toolbox routines that will call the memory manager.
>< Is there a way around this?
>A jGNEFilter is a simple way to get periodic time and you can move memory
>if you need to. The only problem is that you aren't guaranteed that it
>will be called frequently.
Even better is a faceless background application. You can call any
toolbox routine that doesn't provide a user interface. You get time like
any other application.
--Brian Bechtel blob@apple.com "My opinion, not Apple's"
---------------------------
>From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Subject: Self-disposing notification crashes
Date: 16 Sep 94 16:35:09 +1200
Organization: University of Waikato, Hamilton, New Zealand
I'm working on this MPW tool that sends a PostScript stream to a printer via
PAP, and displays whatever the printer sends back. It loads the PDEF 10 code
from the LaserWriter driver (I know, I know, but this is for in-house use,
and I have ways of keeping it working under QuickDraw GX ;-)). However,
I didn't like the PAPStatus call that that library provides, as it's
synchronous, and tends to hang for several seconds if the printer goes away.
So I tried implementing my own version of PAPStatus. My version allocates
a temporary block in the heap, which is used to contain the context for the
call, including pointers to the user's data areas. Once the query starts,
everything runs at interrupt time as a sequence of chained completion routines
from then on, except of course for the last bit of code that gets rid of the
temporary block. This code runs as a notification routine, so that it's safe
for it to make Memory Manager calls.
The notification code is actually copied into the temporary block, and executes
out of there. I did this as part of a strategy for dealing cleanly with aborting
execution of the tool, though admittedly my handling of this is not complete
as yet.
Anyway, this notification routine is very small, and is written in assembler.
Here it is in its entirety:
move.l 4(sp), a0
_NMRemove
move.l NMRec.nmRefCon(a0), a0
_DisposePtr
move.l (sp)+, (sp)
rts
Note that the DisposePtr call is disposing of the block containing the code
(and the notification record) itself! However, I have stepped through this
code with MacsBug, and watched it successfully return from DisposePtr and
execute those last two instructions just fine.
Basically, the problem is, my tool tends to crash, but only the second time
it runs. The first time is always fine: I can send a large multi-page print
job to the printer (with lots of status queries throughout), or I can send
a small one-line query, and it will always work. However, the second time I
try invoking my tool, it will crash.
I finally narrowed it down to one thing: the DisposePtr call in the
notification routine, above. If I no-op out the dispose call (causing a
resultant accumulation of allocated memory blocks in MPW's heap), I can run the
tool multiple times just fine.
Anybody got any ideas as to why this can't work?
Thanks for any help.
Lawrence D'Oliveiro fone: +64-7-856-2889
Info & Tech Services Division fax: +64-7-838-4066
University of Waikato electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+12:00
+++++++++++++++++++++++++++
>From pottier@fregate.ens.fr (Francois Pottier)
Date: 16 Sep 1994 11:28:28 GMT
Organization: Ecole Normale Superieure, PARIS, France
In article <1994Sep16.163509.33240@waikato.ac.nz>,
Lawrence D'Oliveiro, Waikato University <ldo@waikato.ac.nz> wrote:
>
>Anyway, this notification routine is very small, and is written in assembler.
>Here it is in its entirety:
>
> move.l 4(sp), a0
> _NMRemove
> move.l NMRec.nmRefCon(a0), a0
> _DisposePtr
> move.l (sp)+, (sp)
> rts
>
>Note that the DisposePtr call is disposing of the block containing the code
I'm interested in this problem too. My notification routine looks exactly
the same way. It works perfectly, but I'm concerned that it might break in
the future.
Apple has warned against this sort of thing; once the block is freed, you
can't make any assumptions about its contents (so you can't execute code in
it). This makes sense; in a preemptive multitasking system, the block could
very well by allocated by another process before you have time to rts out of
it.
However, I don't see any other way of disposing properly of the Notification
Record. If you want your notification to appear after your normal code is
dead (INITs need to do that), then you must copy the response proc into a
standalone block in the System heap. And if you want to clean up properly,
you should release this block after it's been used. So there appears to be
no way to do the Right Thing here.
I'd be interested in comments...
--
Francois Pottier pottier@dmi.ens.fr
- ----------------------------------------------------------------------------
Check my WWW page at http://acacia.ens.fr:8080/home/pottier/index.html ...
+++++++++++++++++++++++++++
>From Jaeger@fquest.com (Brian Stern)
Date: 16 Sep 1994 15:48:28 GMT
Organization: The University of Texas at Austin, Austin, Texas
In article <35bvgs$h87@nef.ens.fr>, pottier@fregate.ens.fr (Francois
Pottier) wrote:
< However, I don't see any other way of disposing properly of the Notification
< Record. If you want your notification to appear after your normal code is
< dead (INITs need to do that), then you must copy the response proc into a
< standalone block in the System heap. And if you want to clean up properly,
< you should release this block after it's been used. So there appears to be
< no way to do the Right Thing here.
<
< I'd be interested in comments...
<
<
<
<
< --
< Francois Pottier pottier@dmi.ens.fr
< ------------------------------------------------------------------------------
< Check my WWW page at http://acacia.ens.fr:8080/home/pottier/index.html ...
If you check out Dair Grant's Init Shell package, at an ftp site near you,
you'll find some code that gets around this problem. It works by poking
several instructions into ToolScratch, including the disposePtr, and then
jumping to those instructions. I believe this is based on some code that
was in the old usenet mac programmers guide.
Cheers,
--
Brian Stern :-{)}
Jaeger@fquest.com
+++++++++++++++++++++++++++
>From resnick@uiuc.edu (Pete Resnick)
Date: Fri, 16 Sep 1994 15:00:26 -0500
Organization: University of Illinois at Urbana-Champaign
In article <1994Sep16.163509.33240@waikato.ac.nz>, ldo@waikato.ac.nz
(Lawrence D'Oliveiro, Waikato University) wrote:
> Anyway, this notification routine is very small, and is written in assembler.
> Here it is in its entirety:
>
> move.l 4(sp), a0
> _NMRemove
> move.l NMRec.nmRefCon(a0), a0
> _DisposePtr
> move.l (sp)+, (sp)
> rts
>
> Note that the DisposePtr call is disposing of the block containing the code
> (and the notification record) itself! However, I have stepped through this
> code with MacsBug, and watched it successfully return from DisposePtr and
> execute those last two instructions just fine.
Yow!! This would be bad since you can't depend on when that memory is
going to be overwritten, and for you, it's happening in the call to
_DisposePtr. There are two ways around this:
On anything better than a 68010 (which is all Macs except for the classic
one) there is a wonderful little instruction: RTD. That instruction
returns, but also simultaneously deallocates space on the stack. So, what
I do is call _NMRemove (and whatever other cleanup I want to do) and then
move the _DisposePtr and an RTD instruction to the stack:
move.l 4(sp),a0 ; Move the NMRec
_NMRemove ; Remove it
move.l NMRec.nmRefCon(a0),a1 ; Address of code+NMRec into A1
movea.l (sp)+,a0 ; Return address into A0
move.l #$4E740006,-(sp) ; RTD #$0006
move.w #$a01f,-(sp) ; _DisposePtr
move.l a0,-(sp) ; Return address back onto stack
pea 4(sp) ; Address of _DisposePtr on stack
moveq #$1,d0
_HWPriv ; Flush the cache
movea.l a1,a0 ; Address to dispose
rts ; Return to _DisposePtr on stack
So the stack (before the final RTS) looks like:
+0000 <sp + 8>
+0004 <old return address>
+0008 _DisposePtr
+000A RTD #$0006
.....Rest of stack
So when that last RTS executes, it rips the address of sp+8 off of the
stack and jumps to it. The _DisposePtr disposes what's in A0 (the code and
the NMRec), then the RTD takes the old return address off the stack, moves
the stack pointer 6 bytes (past the _DisposePtr and the RTD #$0006), and
jumps to the return address. Frightening, eh?
On the old 68000, you don't have the RTD instruction (nor an instruction
cache), but life is generally a good deal simpler: There is a low memory
global called "ToolScratch", which is an 8-byte scratch area. It stays
constant across the call to _DisposePtr, so what you can do instead is:
move.l 4(sp),a1 ; Move the NMRec
move.l (sp)+,(sp) ; Move the return address into place
_NMRemove ; Remove it
move.l NMRec.nmRefCon(a1),a0 ; Address of code+NMRec into A0
movea.w #ToolScratch,a1 ; Address of the LM global
move.l a1,-(sp) ; Put the address onto the stack
move.l #$a01f4E75,(a1) ; _DisposePtr / RTS
rts
So now the stack looks like:
+0000 <address of ToolScratch>
+0004 <old return address>
.....Rest of stack
And ToolScratch has in it:
_DisposePtr
RTS
This has worked perfectly for me. Executing code on the stack is pretty
wierd, but it works just great.
pr
--
Pete Resnick (...so what is a mojo, and why would one be rising?)
Doctoral Student - Philosophy Department, Gregory Hall, UIUC
System manager - Cognitive Science Group, Beckman Institute, UIUC
Internet: resnick@uiuc.edu
+++++++++++++++++++++++++++
>From jberry@teleport.com (James D. Berry)
Date: Fri, 16 Sep 1994 13:39:16 -0700
Organization: Consultant
In article <1994Sep16.163509.33240@waikato.ac.nz>, ldo@waikato.ac.nz
(Lawrence D'Oliveiro, Waikato University) wrote:
> Anyway, this notification routine is very small, and is written in assembler.
> Here it is in its entirety:
>
> move.l 4(sp), a0
> _NMRemove
> move.l NMRec.nmRefCon(a0), a0
> _DisposePtr
> move.l (sp)+, (sp)
> rts
>
> Note that the DisposePtr call is disposing of the block containing the code
> (and the notification record) itself! However, I have stepped through this
> code with MacsBug, and watched it successfully return from DisposePtr and
> execute those last two instructions just fine.
I can't see the rest of your code, but it strikes me that if for some
reason the NMRemove call is being passed an incorrect value, then you'd be
leaving a bogus link in the NMQueue (because you've deleted the code it's
pointing to) which would cause a crash on the next invokation.
I'm a purest at heart, and also don't like the fact that you're executing
two instructions out of a block that's been disposed. The Modern Memory
Manager, in fact, has a debug mode that'll trash blocks as they're
disposed, which should break your code.
I use the following code to (cleanly?) cleanup following a notification.
Note that it assumes the NMRec and supporting code are all allocated into
a single heap block. It hasn't yet (!!) managed to break the 68K emulator,
though it seems a good target to :-() Now if Apple would just give us a
few NM flags that specify a block to be deleted following notification!
;------------------------------------------------------------
; pascal void NotifyProc(NMRecPtr pRec)
;
; The notify proc. Its sole purpose in life is to
; clean-up following the notification manager.
;------------------------------------------------------------
NotifyProc proc
machine mc68020
entry NotifyProcLen
subq #2,sp ; Extra space 8 bytes --> 10 bytes
move.l 2(sp),-(sp) ; Move Return address
move.l 10(sp),-(sp) ; Move NMRecPtr
lea @StackCodeEnd,a1 ; Move our _DisposePtr code
onto stack
lea 14(sp),a0 ; so that we can suicide cleanly!
move.l -(a1),-(a0) ; rtd #x
move.w -(a1),-(a0) ; _DisposePtr
moveq #6,d0 ; Length of the code
move.l d0,a1 ; into a1
_FlushCodeCacheRange ; Flush the caches where we
wrote code
move.l a0,a1 ; Pointer to our cleanup code
on stack
move.l (sp)+,a0 ; Get NMRecPtr
_NMRemove ; Unqueue the NMRec
jmp (a1) ; Call cleanup code to
dispose the block we're
; currently executing out of
; This code will be moved onto the stack
; before it is executed, so that we don't
; execute code out of a deallocated block
_DisposePtr ; Dispose the
NMRec/code/string block
rtd #6 ; Return to caller,
deallocating this code!
@StackCodeEnd
NotifyProcLen dc.l *-NotifyProc ; Length of our notification proc
endp
--
James Berry
jberry@teleport.com
+++++++++++++++++++++++++++
>From Bruce@hoult.actrix.gen.nz (Bruce Hoult)
Date: Sat, 17 Sep 1994 14:50:34 +1200 (NZST)
Organization: (none)
ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) writes:
> I'm working on this MPW tool that sends a PostScript stream to a printer via
> PAP, and displays whatever the printer sends back.
Heh. I turned your downloader XCMDs into an MPW Tool only about -- what? --
seven years ago.
> It loads the PDEF 10 code
> from the LaserWriter driver (I know, I know, but this is for in-house use
> and I have ways of keeping it working under QuickDraw GX ;-)).
Hmm. Looks as if I'm going to need an update :-(
> I finally narrowed it down to one thing: the DisposePtr call in the
> notification routine, above. If I no-op out the dispose call (causing a
> resultant accumulation of allocated memory blocks in MPW's heap), I can run the
> tool multiple times just fine.
>
> Anybody got any ideas as to why this can't work?
It's not going to like the Modern Memory Manager, which stores some info
inside your data block as soon as you dispose it.
OTOH, if the last two instructions are surviving then it's hard to see what's
going wrong. You *are* allocating a new block and a new copy of the code
each time you use it, right?
Might you not be better to allocate a small block the first time you run
and just leave it alive? And use Gestalt or something to find it each time?
-- Bruce
+++++++++++++++++++++++++++
>From ludis@netcom.com (Ludis Langens)
Date: Sat, 17 Sep 1994 23:28:18 GMT
Organization: Netcom Online Communications Services (408-241-9760 login: guest)
In article <35bvgs$h87@nef.ens.fr> pottier@fregate.ens.fr (Francois Pottier) writes:
>In article <1994Sep16.163509.33240@waikato.ac.nz>,
>Lawrence D'Oliveiro, Waikato University <ldo@waikato.ac.nz> wrote:
>>
>>Anyway, this notification routine is very small, and is written in assembler.
>>Here it is in its entirety:
>>
>> move.l 4(sp), a0
>> _NMRemove
>> move.l NMRec.nmRefCon(a0), a0
>> _DisposePtr
>> move.l (sp)+, (sp)
>> rts
>>
>>Note that the DisposePtr call is disposing of the block containing the code
>
>I'm interested in this problem too. My notification routine looks exactly
>the same way. It works perfectly, but I'm concerned that it might break in
>the future.
>
>Apple has warned against this sort of thing; once the block is freed, you
>can't make any assumptions about its contents (so you can't execute code in
>it). This makes sense; in a preemptive multitasking system, the block could
>very well by allocated by another process before you have time to rts out of
>it.
>
>However, I don't see any other way of disposing properly of the Notification
>Record. If you want your notification to appear after your normal code is
>dead (INITs need to do that), then you must copy the response proc into a
>standalone block in the System heap. And if you want to clean up properly,
>you should release this block after it's been used. So there appears to be
>no way to do the Right Thing here.
To dispose the memory block out of which you are executing, try this:
BlockStart EQU *
...
MOVEQ #$1F,D0 ;Trap number of DisposPtr
_GetTrapAddress OS
MOVE.L A0,A1
LEA BlockStart(PC),A0
JMP (A1)
Use this code as the very last thing you execute. Make sure you have
removed any parameters from the stack (so that an RTS can return to
your caller.) The JMP (A1) goes to the memory manager directly,
bypassing the trap dispatcher. This means that registers D0-D2/A0-A1
may be changed. Once DisposPtr has freed the block, it will return
(directly) to your caller. When you link your code fragment, make sure
that BlockStart is at offset 0 in the memory block. This same trick
can be also be used with handles by adding a RecoverHandle (and getting
the address of DisposHandle.)
Ludis Langens
ludis@netcom.com
+++++++++++++++++++++++++++
>From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Date: 19 Sep 94 14:24:01 +1200
Organization: University of Waikato, Hamilton, New Zealand
In article <jberry-1609941339160001@ip-ce.teleport.com>, jberry@teleport.com (James D. Berry) writes:
> In article <1994Sep16.163509.33240@waikato.ac.nz>, ldo@waikato.ac.nz
> (Lawrence D'Oliveiro, Waikato University) wrote:
>
>> Anyway, this notification routine is very small, and is written in assembler.
>> Here it is in its entirety:
>>
>> move.l 4(sp), a0
>> _NMRemove
>> move.l NMRec.nmRefCon(a0), a0
>> _DisposePtr
>> move.l (sp)+, (sp)
>> rts
>>
>> Note that the DisposePtr call is disposing of the block containing the code
>> (and the notification record) itself! However, I have stepped through this
>> code with MacsBug, and watched it successfully return from DisposePtr and
>> execute those last two instructions just fine.
>
> I can't see the rest of your code, but it strikes me that if for some
> reason the NMRemove call is being passed an incorrect value, then you'd be
> leaving a bogus link in the NMQueue (because you've deleted the code it's
> pointing to) which would cause a crash on the next invokation.
The NMRec address must be correct, because its nmRefCon contains the pointer
to the entire block, which is indeed being correctly disposed. (Like I said,
I checked this with MacsBug.)
> I'm a purest at heart, and also don't like the fact that you're executing
> two instructions out of a block that's been disposed. The Modern Memory
> Manager, in fact, has a debug mode that'll trash blocks as they're
> disposed, which should break your code.
That must be the only memory manager in the world that does that...
Lawrence D'Oliveiro fone: +64-7-856-2889
Info & Tech Services Division fax: +64-7-838-4066
University of Waikato electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+12:00
"Icons are the droppings located at the top and sides of the Windows display."
-- reported in PC Magazine
+++++++++++++++++++++++++++
>From jan3@po.cwru.edu (James A. Nauer)
Date: Mon, 19 Sep 1994 17:18:49 -0400
Organization: Case Western Reserve University
In article <1994Sep19.142402.33297@waikato.ac.nz>, ldo@waikato.ac.nz
(Lawrence D'Oliveiro, Waikato University) wrote:
> In article <jberry-1609941339160001@ip-ce.teleport.com>,
jberry@teleport.com (James D. Berry) writes:
> >
> > I'm a purest at heart, and also don't like the fact that you're executing
> > two instructions out of a block that's been disposed. The Modern Memory
> > Manager, in fact, has a debug mode that'll trash blocks as they're
> > disposed, which should break your code.
>
> That must be the only memory manager in the world that does that...
Not true. I have an anti-virus TSR on my PC which, among other things,
patches the (feeble) DOS memory management routines to zero out all freed
blocks before returning. Naturally, I also have a couple of programs that
fail because they think they can get away with using a few bytes of data
in a block _after_ freeing it :-(.
--
James A. Nauer | "I shall not yield one whit of maturity,
Library Information | not grace, not respectibility, to the
Technologies | passing of time. I declare that I shall
Case Western Reserve Univ. | forever be, if not a child, certainly
(216) 368-MACS (368-6227) | childish" --Kennet Shardik
+++++++++++++++++++++++++++
>From h+@nada.kth.se (Jon W{tte)
Date: Tue, 20 Sep 1994 10:36:19 +0200
Organization: Royal Institute of Something or other
In article <1994Sep19.142402.33297@waikato.ac.nz>,
ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) wrote:
>> two instructions out of a block that's been disposed. The Modern Memory
>> Manager, in fact, has a debug mode that'll trash blocks as they're
>> disposed, which should break your code.
>
>That must be the only memory manager in the world that does that...
Not at all; several malloc() implementations IMMEDIATELY writes
data into the block being disposed, like a pointer in a linked
list of free blocks, or something like that.
Using a block after disposing it is BAD BAD BAD. The
Cleanup/GetTrapAddress/Jump solution is the only clean one, but
depends on the fact that DisposePtr uses register calling
conventions.
Cheers,
/ h+
--
Jon W‰tte (h+@nada.kth.se), Hagagatan 1, 113 48 Stockholm, Sweden
V}ga v{gra nonkonformism!
+++++++++++++++++++++++++++
>From fixer@faxcsl.dcrt.nih.gov (Chris Biscottimeister Tate)
Date: Tue, 20 Sep 1994 18:44:17 GMT
Organization: DCRT, NIH, Bethesda, MD
In article <1994Sep19.142402.33297@waikato.ac.nz>, ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) writes:
>In article <jberry-1609941339160001@ip-ce.teleport.com>, jberry@teleport.com (James D. Berry) writes:
>>
>> I'm a purist at heart, and also don't like the fact that you're executing
>> two instructions out of a block that's been disposed. The Modern Memory
>> Manager, in fact, has a debug mode that'll trash blocks as they're
>> disposed, which should break your code.
>
>That must be the only memory manager in the world that does that...
I seem to recall running into some odd situations in which the system was
writing into unallocated heap memory for some reason. Quickdraw, maybe?
(I would think that executing out of a just-deallocated block is pretty
much a recipe for disaster - certainly in a preemptive-multitasking world
you're doomed if you do it, barring some IMHO unwarranted privileges being
granted to your code...)
- ------------------------------------------------------------------
Christopher Tate | "Apple Guide makes Windows' help engine
MSD, Inc. | look like a quadruple amputee."
fixer@faxcsl.dcrt.nih.gov | -- Pete Gontier (gurgle@dnai.com)
+++++++++++++++++++++++++++
>From rang@winternet.com (Anton Rang)
Date: 21 Sep 1994 01:06:37 GMT
Organization: Trillium Research, Inc.
In article <9668AAA46BA3.6ED60@klkmac018.nada.kth.se> h+@nada.kth.se (Jon W{tte) writes:
>Using a block after disposing it is BAD BAD BAD. The
>Cleanup/GetTrapAddress/Jump solution is the only clean one, but
>depends on the fact that DisposePtr uses register calling
>conventions.
Actually, you're fine with Pascal calling conventions, too, since
the callee is responsible for cleaning up the stack. It's only if you
are trying to use C calling conventions that you'll have problems with
exiting via a call to another routine.
--
Anton Rang (rang@winternet.com)
+++++++++++++++++++++++++++
>From Bruce@hoult.actrix.gen.nz (Bruce Hoult)
Date: Wed, 21 Sep 1994 14:48:10 +1200 (NZST)
Organization: (none)
resnick@uiuc.edu (Pete Resnick) writes:
> On anything better than a 68010 (which is all Macs except for the classic
> one) there is a wonderful little instruction: RTD. That instruction
> returns, but also simultaneously deallocates space on the stack. So, what
> I do is call _NMRemove (and whatever other cleanup I want to do) and then
> move the _DisposePtr and an RTD instruction to the stack:
Arrrrggghhh!!!
There are a *lot* of PowerBook 100's out there, filled to the gills with
RAM, and with a long useful life ahead of them still -- I expect to be
using mine for years yet, even though I've got a PowerMac as my main
machine.
In case you didn't realise, the PB100 uses an original 68000 chip.
-- Bruce
+++++++++++++++++++++++++++
>From ludis@netcom.com (Ludis Langens)
Date: Fri, 23 Sep 1994 21:25:04 GMT
Organization: Netcom Online Communications Services (408-241-9760 login: guest)
In article <9668AAA46BA3.6ED60@klkmac018.nada.kth.se> h+@nada.kth.se (Jon W{tte) writes:
>Using a block after disposing it is BAD BAD BAD. The
>Cleanup/GetTrapAddress/Jump solution is the only clean one, but
>depends on the fact that DisposePtr uses register calling
>conventions.
The Cleanup/GetTrapAddress/Jump solution does not depend upon its target
trap using register calling conventions. A Pascal style trap can also be
called this way - just rearrange the stack appropriately. What it does
depend upon is the register preservation and stack usage of the trap you
are chaining to. It could not be used to chain to a C style function
or to anything that trashes registers which your function must preserve.
If you need to chain to a toolbox trap, the GetTrapAddress step can be
omitted by using a trap with the Auto-pop bit set. This is a very
'official' way of jumping to a trap. (Years ago I used this trick
to create code segments that self UnloadSeg-ed themselves upon returning
to their caller.)
Ludis Langens
ludis@netcom.com
---------------------------
>From fairgate@vespucci.iquest.com (Fairgate Technologies)
Subject: [CWWWW] PowerPlant Tour document available
Date: 23 Sep 1994 15:53:13 -0500
Organization: interQuest -- Fuel for the Mind
Thanks to Marc Paquette of Metrowerks, there's now a PowerPlant Tour
document on CWWWW, along with some other supporting PowerPlant
material.
For those of you who know what CWWWW is, these new goodies are
available on the PowerPlant Central
(http://www.iquest.com/~fairgate/cw/pplant.html) page.
If you haven't visited CWWWW yet, come on down! CWWWW is the official
CodeWarrior World-Wide Web site. IMNSHO there's quite a bit of useful
information there, especially for the relatively undocumented
PowerPlant class library.
Point your WWW browser at http://www.iquest.com/~fairgate.
Cheers,
-Paul
[ If you don't get a reply from me with 48hrs, please resend your message.
The Mail Gods are displeased; incoming mail is sometimes silently dropped. ]
--
Paul Robichaux Fairgate Technologies paul@fairgate.com
Fairgate Technologies does custom Mac development.
Visit the CodeWarrior WWW page at http://www.iquest.com/~fairgate.
---------------------------
End of C.S.M.P. Digest
**********************